package 面试;

public class 反转链表 {
    /**
     * 非递归反转链表
     */
    static class ListNode {
        int val;
        ListNode next;

        ListNode(int x) {
            val = x;
            next = null;
        }
    }

    /**
     * 原地反转
     */
    public static ListNode reverseList(ListNode head) {
        if (head == null)
            return head;
        ListNode dummy = new ListNode(-1);
        dummy.next = head;
        // 设置两根指针 prev（保存 pCur 断开前的状态） 与 pCur（指向需要反转的节点）
        ListNode prev = dummy.next;
        ListNode pCur = prev.next;
        while (pCur != null) {
            // 1.断开pCur
            prev.next = pCur.next;
            // 2.将pCur反转
            pCur.next = dummy.next;
            // 3.连接反转后的结果
            dummy.next = pCur;
            // 4.复原pCur为反转前的状态
            pCur = prev.next;
        }
        return dummy.next;
    }

    /**
     * 头插法反转链表
     * 新建一个链表，遍历原链表，每遍历一个就插到最前面
     */
    public static ListNode reverseListByHead(ListNode head) {
        ListNode dummy = new ListNode(-1);
        // 1.指向需要反转的链表的首部
        ListNode pCur = head;
        while (pCur != null) {
            // 2.保存原链表的下一个节点
            ListNode pNex = pCur.next;
            // 3.开始头插法插入节点到 dummy 中
            pCur.next = dummy.next;
            dummy.next = pCur;
            // 4.最后复原pCur
            pCur = pNex;
        }
        return dummy.next;
    }

    public static void main(String[] args) {
        ListNode l1 = new ListNode(1);
        ListNode l2 = new ListNode(2);
        ListNode l3 = new ListNode(3);
        ListNode l4 = new ListNode(4);
        ListNode l5 = new ListNode(5);
        l1.next = l2;
        l2.next = l3;
        l3.next = l4;
        l4.next = l5;
        ListNode dummy = reverseListByHead(l1);
        while (dummy != null) {
            System.out.print(dummy.val + " ");
            dummy = dummy.next;
        }
    }
}
